import { Request, Response, NextFunction } from 'express';
import prometheusService, { AlertmanagerAlert } from '@services/prometheus';
import llmService from '@services/llm.service';
import logger from '@utils/logger';
import Alert from '@database/models/Alert';

/**
 * Alert Controller
 */
class AlertController {
  /**
   * Get all alerts
   */
  async getAlerts(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { status, severity, page = '1', pageSize = '20' } = req.query;

      // Fetch alerts from Alertmanager
      const alerts = await prometheusService.getActiveAlerts();

      // Apply filters
      let filteredAlerts = alerts;

      // Filter by status
      if (status) {
        const statusArray = (status as string).split(',').filter(s => s);
        if (statusArray.length > 0) {
          filteredAlerts = filteredAlerts.filter(alert =>
            statusArray.includes(alert.labels.status || 'active')
          );
        }
      }

      // Filter by severity
      if (severity) {
        const severityArray = (severity as string).split(',').filter(s => s);
        if (severityArray.length > 0) {
          filteredAlerts = filteredAlerts.filter(alert =>
            severityArray.includes(alert.labels.severity || 'unknown')
          );
        }
      }

      // Pagination
      const pageNum = parseInt(page as string, 10);
      const pageSizeNum = parseInt(pageSize as string, 10);
      const start = (pageNum - 1) * pageSizeNum;
      const end = start + pageSizeNum;
      const paginatedAlerts = filteredAlerts.slice(start, end);

      // Convert to frontend format (without auto AI analysis)
      const formattedAlerts = paginatedAlerts.map((alert) => {
        return {
          id: alert.fingerprint,
          alertname: alert.labels.alertname || 'Unknown',
          severity: alert.labels.severity || 'unknown',
          status: alert.status.state === 'active' ? 'active' : 'resolved',
          instance: alert.labels.instance || 'unknown',
          job: alert.labels.job || 'unknown',
          startsAt: new Date(alert.startsAt),
          endsAt: alert.endsAt ? new Date(alert.endsAt) : undefined,
          description: alert.annotations.description || alert.annotations.summary || '',
          labels: alert.labels,
          annotations: alert.annotations,
        };
      });

      res.status(200).json({
        success: true,
        data: formattedAlerts,
        pagination: {
          current: pageNum,
          pageSize: pageSizeNum,
          total: filteredAlerts.length,
        },
      });
    } catch (error) {
      logger.error('Failed to get alerts:', error as Error);
      next(error);
    }
  }

  /**
   * Get single alert details
   */
  async getAlert(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;
      const alerts = await prometheusService.getActiveAlerts();
      const alert = alerts.find(a => a.fingerprint === id);

      if (!alert) {
        res.status(404).json({
          success: false,
          message: 'Alert not found',
        });
        return;
      }

      const formattedAlert = {
        id: alert.fingerprint,
        alertname: alert.labels.alertname || 'Unknown',
        severity: alert.labels.severity || 'unknown',
        status: alert.status.state === 'active' ? 'active' : 'resolved',
        instance: alert.labels.instance || 'unknown',
        job: alert.labels.job || 'unknown',
        startsAt: new Date(alert.startsAt),
        endsAt: alert.endsAt ? new Date(alert.endsAt) : undefined,
        description: alert.annotations.description || alert.annotations.summary || '',
        labels: alert.labels,
        annotations: alert.annotations,
        aiAnalysis: {
          summary: `System detected ${alert.labels.alertname} alert`,
          rootCause: alert.annotations.description || 'Further analysis required',
          suggestions: ['Check related service status', 'Review system logs', 'Contact relevant team'],
          relatedAlerts: [],
          confidence: 0.75,
          tags: [alert.labels.severity, alert.labels.job].filter(Boolean),
        },
      };

      res.status(200).json({
        success: true,
        data: formattedAlert,
      });
    } catch (error) {
      logger.error(`Failed to get alert ${req.params.id}:`, error as Error);
      next(error);
    }
  }

  /**
   * Acknowledge alert
   */
  async acknowledgeAlert(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;
      const { comment } = req.body;

      // Get current user from auth middleware
      const userId = req.user?._id.toString();
      const userName = req.user?.email || 'Unknown User';

      // Find or create alert in database
      let alert = await Alert.findOne({ fingerprint: id });

      if (!alert) {
        // If alert doesn't exist in DB, fetch from Prometheus and create it
        const alerts = await prometheusService.getActiveAlerts();
        const prometheusAlert = alerts.find(a => a.fingerprint === id);

        if (!prometheusAlert) {
          res.status(404).json({
            success: false,
            message: 'Alert not found',
          });
          return;
        }

        // Create alert in database
        alert = new Alert({
          fingerprint: prometheusAlert.fingerprint,
          alertname: prometheusAlert.labels.alertname,
          labels: prometheusAlert.labels,
          annotations: prometheusAlert.annotations,
          status: 'acknowledged',
          severity: prometheusAlert.labels.severity as any,
          startsAt: new Date(prometheusAlert.startsAt),
          endsAt: prometheusAlert.endsAt ? new Date(prometheusAlert.endsAt) : undefined,
          actions: [],
        });
      } else {
        // Update existing alert status
        alert.status = 'acknowledged' as any;
      }

      // Add acknowledge action to history
      alert.actions.push({
        actionType: 'acknowledge',
        userId: userId as any,
        userName,
        comment,
        timestamp: new Date(),
      });

      await alert.save();

      logger.info(`Alert ${id} acknowledged by ${userName}`);

      res.status(200).json({
        success: true,
        message: 'Alert acknowledged successfully',
        data: alert,
      });
    } catch (error) {
      logger.error(`Failed to acknowledge alert ${req.params.id}:`, error as Error);
      next(error);
    }
  }

  /**
   * Resolve alert
   */
  async resolveAlert(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;
      const { comment } = req.body;

      // Get current user from auth middleware
      const userId = req.user?._id.toString();
      const userName = req.user?.email || 'Unknown User';

      // Find or create alert in database
      let alert = await Alert.findOne({ fingerprint: id });

      if (!alert) {
        // If alert doesn't exist in DB, fetch from Prometheus and create it
        const alerts = await prometheusService.getActiveAlerts();
        const prometheusAlert = alerts.find(a => a.fingerprint === id);

        if (!prometheusAlert) {
          res.status(404).json({
            success: false,
            message: 'Alert not found',
          });
          return;
        }

        // Create alert in database
        alert = new Alert({
          fingerprint: prometheusAlert.fingerprint,
          alertname: prometheusAlert.labels.alertname,
          labels: prometheusAlert.labels,
          annotations: prometheusAlert.annotations,
          status: 'resolved',
          severity: prometheusAlert.labels.severity as any,
          startsAt: new Date(prometheusAlert.startsAt),
          endsAt: new Date(),
          actions: [],
        });
      } else {
        // Update existing alert status
        alert.status = 'resolved' as any;
        alert.endsAt = new Date();
      }

      // Add resolve action to history
      alert.actions.push({
        actionType: 'resolve',
        userId: userId as any,
        userName,
        comment,
        timestamp: new Date(),
      });

      await alert.save();

      logger.info(`Alert ${id} resolved by ${userName}`);

      res.status(200).json({
        success: true,
        message: 'Alert resolved successfully',
        data: alert,
      });
    } catch (error) {
      logger.error(`Failed to resolve alert ${req.params.id}:`, error as Error);
      next(error);
    }
  }

  /**
   * Silence alert
   */
  async silenceAlert(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;
      const { duration = 60, comment = 'Silenced by user' } = req.body;

      await prometheusService.silenceAlert(id ?? "", duration, comment);

      res.status(200).json({
        success: true,
        message: `Alert silenced for ${duration} minutes`,
      });
    } catch (error) {
      logger.error(`Failed to silence alert ${req.params.id}:`, error as Error);
      next(error);
    }
  }

  /**
   * AI alert analysis (on-demand)
   */
  async analyzeAlertWithAI(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;

      // Get alert information
      const alerts = await prometheusService.getActiveAlerts();
      const alert = alerts.find((a) => a.fingerprint === id);

      if (!alert) {
        res.status(404).json({
          success: false,
          message: 'Alert not found',
        });
        return;
      }

      // Analyze alert using LLM
      const aiAnalysis = await llmService.analyzeAlert({
        alertName: alert.labels.alertname || 'Unknown',
        severity: alert.labels.severity || 'unknown',
        description: alert.annotations.description || alert.annotations.summary || '',
        labels: alert.labels,
        annotations: alert.annotations,
      });

      res.status(200).json({
        success: true,
        data: aiAnalysis,
      });
    } catch (error) {
      logger.error(`Failed to analyze alert ${req.params.id} with AI:`, error as Error);
      next(error);
    }
  }

  /**
   * Create ticket from alert
   */
  async createTicketFromAlert(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { alertId } = req.params;
      const { title, priority } = req.body;

      // TODO: Implement ticket creation logic
      const ticket = {
        id: `ticket-${Date.now()}`,
        title: title || 'Alert Ticket',
        status: 'open',
        priority: priority || 'medium',
        createdAt: new Date(),
        relatedAlertId: alertId,
      };

      logger.info(`Created ticket ${ticket.id} from alert ${alertId}`);

      res.status(201).json({
        success: true,
        data: ticket,
        message: 'Ticket created successfully',
      });
    } catch (error) {
      logger.error(`Failed to create ticket from alert ${req.params.alertId}:`, error as Error);
      next(error);
    }
  }

  /**
   * Get alert statistics
   */
  async getAlertStatistics(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const alerts = await prometheusService.getActiveAlerts();

      const statistics = {
        total: alerts.length,
        critical: alerts.filter(a => a.labels.severity === 'critical').length,
        high: alerts.filter(a => a.labels.severity === 'high').length,
        medium: alerts.filter(a => a.labels.severity === 'medium').length,
        low: alerts.filter(a => a.labels.severity === 'low').length,
        active: alerts.filter(a => a.status.state === 'active').length,
        resolved: alerts.filter(a => a.status.state !== 'active').length,
      };

      res.status(200).json({
        success: true,
        data: statistics,
      });
    } catch (error) {
      logger.error('Failed to get alert statistics:', error as Error);
      next(error);
    }
  }
}

export default new AlertController();
